package cn.xzc.job.cocurrent;

import cn.xzc.job.util.ClassUtil;

import java.util.concurrent.*;

/**
 * 线程池创建
 *
 * @author xzc
 * 当前时间 2024-02-12 21:30:00
 */
public abstract class ExecutorConfigurationSupport extends CustomizableThreadFactory {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ExecutorConfigurationSupport.class);


    private ThreadFactory threadFactory = this;

    private boolean threadNamePrefixSet = false;

    private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();

    /**
     * 等待任务关闭:false 强制关闭 true 不强制关闭
     */
    private boolean waitForTasksToCompleteOnShutdown = false;

    private long awaitTerminationMillis = 0;


    
    private ExecutorService executor;


    /**
     * Set the ThreadFactory
     */
    public void setThreadFactory(
                                 ThreadFactory threadFactory) {
        this.threadFactory = (threadFactory != null ? threadFactory : this);
    }

    @Override
    public void setThreadNamePrefix(
                                    String threadNamePrefix) {
        super.setThreadNamePrefix(threadNamePrefix);
        this.threadNamePrefixSet = true;
    }

    /**
     * Set the RejectedExecutionHandler to use for the ExecutorService. Default is the ExecutorService's default abort policy.
     * 设置线程池拒绝策略
     */
    public void setRejectedExecutionHandler(
                                            RejectedExecutionHandler rejectedExecutionHandler) {
        this.rejectedExecutionHandler =
                (rejectedExecutionHandler != null ? rejectedExecutionHandler : new ThreadPoolExecutor.AbortPolicy());
    }

    /**
     * 等待任务关闭:false 强制关闭 true 不强制关闭
     *
     * @param waitForJobsToCompleteOnShutdown 设置线程池不强制关闭标志
     */
    public void setWaitForTasksToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
        this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
    }

    /**
     * 调用线程池关闭强制等待时间【秒】
     *
     * @param awaitTerminationSeconds 强制等待时间【毫秒】
     */
    public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
        this.awaitTerminationMillis = awaitTerminationSeconds * 1000L;
    }

    /**
     * 调用线程池关闭强制等待时间【毫秒】
     *
     * @param awaitTerminationMillis 强制等待时间【毫秒】
     */
    public void setAwaitTerminationMillis(long awaitTerminationMillis) {
        this.awaitTerminationMillis = awaitTerminationMillis;
    }

    /**
     * Set up the ExecutorService.
     * 对象初始化要调用的方法
     */
    public void init() {
        if (log.isDebugEnabled()) {
            log.debug("Initializing ExecutorService" + (" '" + getBeanName() + "'"));
        }
        if (!this.threadNamePrefixSet) {
            setThreadNamePrefix(getBeanName() + "-");
        }
        this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
    }

    /**
     * 创建线程池
     *
     * @param threadFactory            线程池线程Factory
     * @param rejectedExecutionHandler 线程池拒绝策略
     * @return 线程池
     */
    protected abstract ExecutorService initializeExecutor(
            ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler);


    /**
     * Calls {@code shutdown} when the BeanFactory destroys the task executor instance.
     * 销毁时关闭线程池
     */
    public void destroy() {
        shutdown();
    }

    /**
     * Perform a shutdown on the underlying ExecutorService.
     * 线程池关闭
     */
    public void shutdown() {
        if (log.isDebugEnabled()) {
            log.debug("Shutting down ExecutorService" + (" '" + getBeanName() + "'"));
        }
        if (this.executor != null) {
            //关闭线程池
            if (this.waitForTasksToCompleteOnShutdown) {
                //不强制关闭
                this.executor.shutdown();
            } else {
                //强制关闭
                for (Runnable remainingJob : this.executor.shutdownNow()) {
                    cancelRemainingTask(remainingJob);
                }
            }
            awaitTerminationIfNecessary(this.executor);
        }
    }

    /**
     * Cancel the given remaining task which never commended execution,
     * 强制关闭runnable
     *
     * @param task the task to cancel (typically a {@link RunnableFuture}) 任务
     */
    protected void cancelRemainingTask(Runnable task) {
        if (task instanceof Future) {
            ((Future<?>) task).cancel(true);
        }
    }

    /**
     * Wait for the executor to terminate, according to the value of the {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"} property.
     * 等待线程池关闭
     */
    private void awaitTerminationIfNecessary(ExecutorService executor) {
        if (this.awaitTerminationMillis > 0) {
            try {
                //根据超时等待时间判断线程池是否关闭:【该线程池没有关闭】
                if (!executor.awaitTermination(this.awaitTerminationMillis, TimeUnit.MILLISECONDS) && log.isWarnEnabled()) {
                    log.warn("Timed out while waiting for executor" +
                            (" '" + getBeanName() + "'") + " to terminate");
                }
            } catch (InterruptedException ex) {
                if (log.isWarnEnabled()) {
                    log.warn("Interrupted while waiting for executor" +
                            (" '" + getBeanName() + "'") + " to terminate");
                }
                Thread.currentThread().interrupt();
            }
        }
    }

    public String getBeanName() {
        return ClassUtil.getShortName(this.getClass());
    }

}
